package com.fingard.dsp.bank.directbank.spdb01;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Date;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.bankInterface.IAuthorizeForRec;
import com.fingard.dsp.bank.directbank.spdb01.authforrec.CertificateCoder;
import com.fingard.dsp.bank.directbank.spdb01.authforrec.SecurityAES;
import com.fingard.dsp.bank.directbank.spdb01.authforrec.SocketHelper;
import com.fingard.dsp.bank.directbank.spdb01.authforrec.StringUtils;
import com.fingard.dsp.bank.directbank.spdb01.authforrec.XMLGetValueHelper;
import com.fingard.dsp.bank.reqrespobj.authforrec.ReqAuthForRec;
import com.fingard.dsp.bank.reqrespobj.authforrec.ReqQryAuthForRec;
import com.fingard.dsp.bank.reqrespobj.authforrec.ReqQryRecAuthInfo;
import com.fingard.dsp.bank.reqrespobj.authforrec.RetAtsAuthForRec;
import com.fingard.dsp.bank.reqrespobj.authforrec.RetAtsQryAuthForRec;
import com.fingard.dsp.bank.reqrespobj.authforrec.RetAtsQryRecAuthInfo;
import com.fingard.dsp.bank.reqrespobj.authforrec.detail.ReqAuthForRecDetail;
import com.fingard.dsp.bank.reqrespobj.authforrec.detail.RetAtsQryAuthForRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.util.DateHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

public class SPDB01AuthorizeForRec extends SPDB01Base implements IAuthorizeForRec {


   

    @Override
    public RetAtsAuthForRec d_auth(ReqAuthForRec p_req) {
        RetAtsAuthForRec retAts = null;
        try {
            if (getBankConfig().getValueAsBool("authByAT23")) {
                retAts = authByAT23(p_req);
            } else {
                retAts = oldAuth(p_req);
            }
        } catch (Exception ex) {
            this.WriteBankLogLn(ex);
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
        }
        return retAts;
    }

    private RetAtsAuthForRec authByAT23(ReqAuthForRec p_req) throws Exception {
        RetAtsAuthForRec retAts = new RetAtsAuthForRec(p_req.reqHeader);
        ReqAuthForRecDetail detail = null;
        boolean sucFlag = true;
        String batchNo = p_req.reqSeqID;
        //错误信息
        String returnMsg = "";
        //储存该批次的账号信息
        StringBuilder sb = new StringBuilder();
        String costItemCode = "";
        while (p_req.readRecord()) {
            SPDB01Header tmpBnkHeader = new SPDB01Header();
            detail = p_req.readedDetail;
            tmpBnkHeader.transCode = "AT23";
            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            xmlWriter.writeStartElement("body");
            xmlWriter.writeElementString("transMasterID", bankFront.protocolNo);//交易客户号Y(10)
            xmlWriter.writeElementString("projectNumber", bankFront.corpNo);
            String mapCostKey = "auth|" + p_req.ownAct;
            costItemCode = costItemCodeMap(mapCostKey);
            xmlWriter.writeElementString("costItemCode", costItemCode);//费项编码Y(5)
            xmlWriter.writeElementString("signDate", Format.Date8Format.format(new Date()));//签约日期Y(8)
            xmlWriter.writeElementString("elecChequeNo", batchNo);//电子凭证号Y(32)
            String isSpdb = "1";
            if ("1".equals(detail.sameBnk)) {
                isSpdb = "0";//0-同为浦发
            }
            xmlWriter.writeElementString("isSpdbAccount", isSpdb);//是否浦发账户Y(8)}
            xmlWriter.writeElementString("acctNo", detail.oppAct);//客户账号Y(32)
            sb.append("," + detail.oppAct);
            String cardtype = "";
            //payeeType 收款人账户类型 0-对公账号  1-卡  8-活期存折
            if ("1".equals(detail.cardType)) {
                cardtype = "8";
            } else {
                cardtype = "1";
            }
            //1-存折,2-卡,3-贷记卡,4-准贷记卡
            //0:对公帐号 1:卡 2:活期一本通 8:活期存折 9:内部帐/表外帐
            xmlWriter.writeElementString("cusAccountType", cardtype);//客户账号类型Y(1)
            xmlWriter.writeElementString("cusAccountName", detail.oppActName);//客户账号名称Y(120)
            xmlWriter.writeElementString("IDNumber", detail.certNum);//证件号码Y(50)
            xmlWriter.writeElementString("IDType", convertCertTypeToBank(detail.certType));//证件类型Y(2)
            xmlWriter.writeElementString("adversaryBankNo",   detail.cnapsCode);//对手行行号N(32)
            xmlWriter.writeElementString("adversaryBankName", "");//对手行行名N(120)
            xmlWriter.writeElementString("payBankNo", "");//支付行号N(32)
            xmlWriter.writeElementString("phoneNumber", "");//手机号N(15)
            xmlWriter.writeElementString("contactAddress", "");//联系地址N(200)
            xmlWriter.writeElementString("agreementBeginDate", "");//协议开始时间N(8)
            String deadline = detail.deadLine.substring(0, 4) + detail.deadLine.substring(5, 7) + detail.deadLine.substring(8, 10);
            xmlWriter.writeElementString("agreementEndDate", deadline);//协议结束时间N(8)
            xmlWriter.writeElementString("amount", getValueAsString("limitedAmt"));//单笔限额Y(18)
            xmlWriter.writeElementString("currency", "CNY");//币种N(3)
            xmlWriter.writeElementString("note1", "");//备用字段1N(60)
            xmlWriter.writeElementString("note2", "");//备用字段2N(60)
            xmlWriter.writeEndDocument();//写入报文完成
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), tmpBnkHeader);//发送银行
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                //解析银行返回
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String returnCode = tmpBkReader.getFirstText("/packet/head/returnCode");
                    returnMsg = tmpBkReader.getFirstText("/packet/head/returnMsg");
                    if (com.fingard.text.StringHelper.hasAnyChar(returnCode)) {
                        retAts.respCode = "0";
                        if (returnMsg == null || "".equals(returnMsg)) {
                            returnMsg = tmpBkReader.getFirstText("/packet/body/returnMsg");
                        }
                        //0:成功
                        //1:失败
                        //2: 处理中
                        String signStatus = tmpBkReader.getFirstText("/packet/body/signStatus");
                        if ("AAAAAAA".equals(returnCode) && signStatus != null) {
                            if ("1".equals(signStatus)) {
                                sucFlag = false;
                                break;
                            }
                        } else {
                            retAts.respCode = "0";
                            retAts.respInfo = returnMsg;
                            retAts.retCode = returnCode;
                            retAts.retMsg = returnMsg;
                            retAts.reqSeqID = p_req.reqSeqID;
                            sucFlag = false;
                            break;
                        }
                    } else {
                        retAts.respCode = "-1";
                        if (com.fingard.text.StringHelper.hasAnyChar(returnMsg)) {
                            retAts.respInfo = returnMsg;
                        } else {
                            retAts.respInfo = "returnCode节点为空";
                        }
                        sucFlag = false;
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpSbMsg.toString();
                    sucFlag = false;
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
                sucFlag = false;
            }
        }
        if (sucFlag) {
            retAts.respCode = "0";
            retAts.respInfo = "签约发起成功";
            retAts.reqSeqID = p_req.reqSeqID;
            retAts.retCode = "AAAAAAA+0";
            
        }
        
        String dataPath = getDataFileDirectory(new Date()) + File.separator + "qryAuth" + File.separator + batchNo;
        sb.delete(0, 1);
        sb.append("||" + costItemCode);
        FileHelper.writeFile(dataPath, sb.toString(), getCharset());
        this.WriteBankLogLn("映射信息写入"+dataPath);
        retAts.writeRetToATS();
        return retAts;
    }

    private RetAtsAuthForRec oldAuth(ReqAuthForRec p_req) {
        RetAtsAuthForRec retAts = new RetAtsAuthForRec(p_req.reqHeader);
        ActSetItem actItem = getBankConfig().getActSetItem(p_req.ownAct, "authForRec");

        if (actItem != null) {
            try {
                getSessionKey(actItem);
                Date timeNow = new Date();
                StringBuilder sbDt = new StringBuilder();
                sbDt.append("authCode|oppAct|oppActName|ReturnCode|ReturnMsg|SignSerialNo|SignStatus|DeadLine\r\n");
                while (p_req.readRecord()) {
                    XmlTextWriter xmlWriter = new XmlTextWriter();
                    xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
                    xmlWriter.writeStartElement("Message");
                    xmlWriter.writeStartElement("Head");
                    xmlWriter.writeElementString("TransCode", "21");
                    xmlWriter.writeElementString("TChannelNo", actItem.termId);
                    xmlWriter.writeElementString("CorpNo", actItem.corpCode);
                    xmlWriter.writeElementString("FeeNo", actItem.busCode);
                    xmlWriter.writeEndElement();
                    xmlWriter.writeStartElement("Body");
                    if (p_req.readedDetail.sameBnk == null || p_req.readedDetail.sameBnk.equals("1")) {
                        xmlWriter.writeElementString("IsSpdbAcnt", "0");
                    } else {
                        xmlWriter.writeElementString("IsSpdbAcnt", "1");
                    }
                    xmlWriter.writeElementString("PayAcntCode", p_req.readedDetail.oppAct);
                    if (p_req.readedDetail.isPrivate == null || p_req.readedDetail.isPrivate.equals("1")) {
                        xmlWriter.writeElementString("PayAcntType", "1");
                    } else {
                        xmlWriter.writeElementString("PayAcntType", "0");
                    }
                    xmlWriter.writeElementString("PayAcntName", p_req.readedDetail.oppActName);
                    xmlWriter.writeElementString("OpenBankCode", p_req.readedDetail.cnapsCode);
                    xmlWriter.writeElementString("ChargeLimit", actItem.amtLimit);
                    xmlWriter.writeElementString("BeginDate", Format.Date8Format.format(new Date()));
                    String endDate = "20991231";
                    if (p_req.readedDetail.deadLine != null && p_req.readedDetail.deadLine.length() > 0) {
                        if (p_req.readedDetail.deadLine.length() >= 10) {
                            endDate = DateHelper.convertD10toD8(p_req.readedDetail.deadLine);
                        } else {
                            endDate = p_req.readedDetail.deadLine;
                        }
                    }
                    xmlWriter.writeElementString("EndDate", endDate);
                    xmlWriter.writeElementClosed("LinkedAddr");
                    xmlWriter.writeElementClosed("LinkedTel");
                    xmlWriter.writeEndDocument();
                    String xmlPck = xmlWriter.toXmlString();

                    WriteBankLogStep2("发送的明文：" + xmlPck);

                    String sessionKey = bankFront.customMap.get("authForRec-sessionKey");
                    byte[] bytesToSend = SecurityAES.encrypt(xmlPck, sessionKey);

                    String strToSend = StringUtils.bytesToHexString(bytesToSend);
                    xmlWriter = null;
                    xmlWriter = new XmlTextWriter();
                    xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
                    xmlWriter.writeStartElement("Message");
                    xmlWriter.writeStartElement("Head");
                    xmlWriter.writeElementString("CorpNo", actItem.corpCode);
                    xmlWriter.writeElementString("Version", "1.0");
                    xmlWriter.writeElementString("ReqTime", bankFront.customMap.get("authForRec-timeStr"));
                    xmlWriter.writeEndElement();
                    xmlWriter.writeStartElement("Body");
                    xmlWriter.writeElementString("ReqData", strToSend);
                    xmlWriter.writeEndDocument();

                    String pckSend = xmlWriter.toXmlString();

                    WriteBankLogStep2("发送的密文：" + pckSend);

                    byte[] result = sentBytesToBank(pckSend.getBytes(getCharset("authForRec")));
                    //byte[] result = FileHelper.readFileBytes("D:\\getToWork\\14-filesForDevelop\\SPDB01\\授权提交.txt");

                    String resultXml = new String(result);
                    WriteBankLogStep3("接收的密文：" + resultXml);
                    String xmlContent = XMLGetValueHelper.getInstance(resultXml).getString("ResData");

                    xmlContent = SecurityAES.decrypt(StringUtils.hexStringToBytes(xmlContent), sessionKey);
                    WriteBankLogStep3("接收的明文：" + xmlContent);

                    int idxEnd = xmlContent.indexOf("</Message>");
                    if (idxEnd > 0) {
                        xmlContent = xmlContent.substring(0, idxEnd + 10);
                    }
                    XMLGetValueHelper xmlHelper = XMLGetValueHelper.getInstance(xmlContent);
                    String ReturnCode = xmlHelper.getString("ReturnCode");
                    String ReturnMsg = xmlHelper.getString("ReturnMsg");
                    String SignSerialNo = xmlHelper.getString("SignSerialNo");
                    String SignStatus = xmlHelper.getString("SignStatus");

                    //sbDt.append("authCode|oppAct|oppActName|ReturnCode|ReturnMsg|SignSerialNo|SignStatus\r\n");
                    sbDt.append(p_req.readedDetail.authCode + "|" + p_req.readedDetail.oppAct + "|" + p_req.readedDetail.oppActName + "|" + ReturnCode + "|" + ReturnMsg + "|" + SignSerialNo + "|" + SignStatus + "|" + p_req.readedDetail.deadLine + "\r\n");


                    retAts.respCode = "0";
                    retAts.respInfo = "提交成功";
                    retAts.reqSeqID = p_req.reqSeqID;
                    retAts.retCode = "0";
                }
                String dataDir = this.getDataFileDirectory(timeNow);
                File fileDir = new File(dataDir);
                if (!fileDir.exists()) {
                    fileDir.mkdirs();
                }
                File tmpFile = new File(fileDir, p_req.reqSeqID + ".txt");
                if (tmpFile.exists()) {
                    tmpFile = new File(fileDir, p_req.reqSeqID + "." + Format.DateTime17SSSFormat.format(timeNow) + ".txt");
                }
                tmpFile.createNewFile();
                FileHelper.writeFile(tmpFile, sbDt.toString(), getCharset("authForRec"));

            } catch (Exception ex) {
                this.WriteBankLogLn(ex);
                retAts.respCode = "-1";
                retAts.respInfo = ex.getMessage();
            }
        } else {
            retAts.respCode = "-1";
            retAts.respInfo = "缺少账号" + p_req.ownAct + "的配置";
        }

        retAts.writeRetToATS();
        return retAts;
    }


    @Override
    public RetAtsQryAuthForRec d_qry_auth(ReqQryAuthForRec p_req) throws Exception {
        RetAtsQryAuthForRec retAts = null;
        if (getBankConfig().getValueAsBool("authByAT23")) {
            retAts = newQryAuth(p_req);
        } else {
            retAts = oldQryAuth(p_req);
        }
        return retAts;
    }

    private RetAtsQryAuthForRec newQryAuth(ReqQryAuthForRec p_req) throws Exception {
        RetAtsQryAuthForRec retAts = new RetAtsQryAuthForRec(p_req.reqHeader);
        retAts.writeStart();
        RetAtsQryAuthForRecDetail p_detail = null;
        String dataPath = getDataFileDirectory(new Date()) + File.separator + "qryAuth";
        String[] res = FileHelper.listFiles(dataPath);
        String batchNo = p_req.reqSeqID;//批次号
        String costItemCode = "";
        String[] actList = null;
       // 查询该批次签约账号的act
        for (String re : res) {
            if (re.startsWith(batchNo)) {
            	String fileTxt = FileHelper.readFileText(dataPath + File.separator + re, getCharset());
            	String[] spValues = fileTxt.split("\\|\\|");
                costItemCode = spValues[1];
                actList = spValues[0].split(",");
            }
        }
        SPDB01Header tmpBnkHeader = new SPDB01Header();
        tmpBnkHeader.transCode = "AT25";
        //costItemCode = costItemCodeMap(costItemCode);
        boolean sucFlag = true;
        for (String oppAct : actList) {
            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            xmlWriter.writeStartElement("body");
            xmlWriter.writeElementString("transMasterID", bankFront.protocolNo);//交易客户号Y(10)
            xmlWriter.writeElementString("projectNumber", bankFront.corpNo);
            xmlWriter.writeElementString("costItemCode", costItemCode);//费项编码Y(5)
            xmlWriter.writeElementString("cusSignID", "");//与签约账号二选一
            xmlWriter.writeElementString("payerAccount", oppAct);//签约账号act
            xmlWriter.writeElementString("note1", "");//备用1
            xmlWriter.writeElementString("note2", "");//备用2
            xmlWriter.writeEndElement();
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), tmpBnkHeader);//发送银行
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                //解析银行返回
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String returnCode = tmpBkReader.getFirstText("/packet/head/returnCode");
                    String returnMsg = tmpBkReader.getFirstText("/packet/head/returnMsg");
                    if (com.fingard.text.StringHelper.hasAnyChar(returnCode)) {
                        retAts.respCode = "0";
                        if (returnMsg == null || "".equals(returnMsg)) {
                            returnMsg = tmpBkReader.getFirstText("/packet/body/returnMsg");
                        }
                        //0:已签约
                        //1:已解约
                        //2:无签约
                        String signStatus = tmpBkReader.getFirstText("/packet/body/signStatus");
                        p_detail = new RetAtsQryAuthForRecDetail();
                        if ("AAAAAAA".equals(returnCode) && signStatus != null) {
                            p_detail.transState = returnCode + "+" + signStatus;
                            if ("0".equals(signStatus)) {
                                p_detail.transState = "2";
                                p_detail.payInfo = "授权成功";
                            } else if ("2".equals(signStatus)) {
                                p_detail.transState = "3";
                                p_detail.payInfo = "无签约";
                            } else if ("1".equals(signStatus)) {
                                p_detail.transState = "1";
                                p_detail.payInfo = "已解约";
                            }
                            retAts.reqSeqID = p_req.reqSeqID;
                            p_detail.authCode = tmpBkReader.getFirstText("/packet/body/cusSignID");//客户签约ID 集中代收付系统唯一客户签约ID
                            p_detail.iSeqno = tmpBkReader.getFirstText("/packet/body/requestJnl");//请求流水号
                            p_detail.oppAct = tmpBkReader.getFirstText("/packet/body/cusAccount");//客户账号
                            p_detail.oppActName = tmpBkReader.getFirstText("/packet/body/cusAccountName");//客户账号名称
                            p_detail.contractNo = tmpBkReader.getFirstText("/packet/body/cusSignID"); //客户签约ID 集中代收付系统唯一客户签约ID
                            p_detail.deadLine = tmpBkReader.getFirstText("/packet/body/agreementEndDate");//协议结束时间 yyyyMMdd
                            p_detail.payType = tmpBkReader.getFirstText("/packet/body/transTypeCode");//交易类型编码1:代收       2: 代付
                        } else {
                            retAts.respCode = "0";
                            retAts.transState = "3";
                            retAts.respInfo = returnMsg;
                            retAts.reqSeqID = p_req.reqSeqID;
                        }
                    } else {
                        retAts.respCode = "-1";
                        if (com.fingard.text.StringHelper.hasAnyChar(returnMsg)) {
                            retAts.respInfo = returnMsg;
                        } else {
                            retAts.respInfo = "returnCode节点为空";
                        }
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpSbMsg.toString();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }
        }

        retAts.writeAfterDetail();
        return retAts;
    }

    private RetAtsQryAuthForRec oldQryAuth(ReqQryAuthForRec p_req) {
        RetAtsQryAuthForRec retAts = new RetAtsQryAuthForRec(p_req.reqHeader);
        retAts.reqSeqID = p_req.reqSeqID;
        retAts.writeStart();
        boolean isExistResult = false;
        retAts.respCode = "0";
        Date qryDate = new Date();
        for (int i = 0; i < 15; i++) {//查最近15天
            if (i > 0) {
                qryDate = DateHelper.addDays(qryDate, -1);
            }
            String dataDir = this.getDataFileDirectory(qryDate);
            File tmpFile = new File(dataDir, p_req.reqSeqID + ".txt");
            if (tmpFile.exists()) {
                isExistResult = true;
                BufferedReader reader = null;
                try {
                    reader = new BufferedReader(new FileReader(tmpFile));
                    String eachLine = reader.readLine();//第一行是列名
                    while (eachLine != null) {
                        eachLine = reader.readLine();//第二行开始是数据
                        //"[0]authCode|[1]oppAct|[2]oppActName|[3]ReturnCode|[4]ReturnMsg|[5]SignSerialNo|[6]SignStatus\r\n"
                        if (eachLine != null) {
                            eachLine = eachLine.trim();
                            if (eachLine.length() > 0) {
                                String[] values = eachLine.split("\\|");
                                RetAtsQryAuthForRecDetail dt = new RetAtsQryAuthForRecDetail();
                                String SignStatus = "";
                                if (values.length > 6) {
                                    SignStatus = values[6];
                                }
                                dt.payCode = values[3] + "+" + SignStatus;
                                if (values.length > 7) {
                                    dt.deadLine = values[7];
                                }
                                if (SignStatus != null) {//SignStatus 0成功，1失败
                                    if ("0".equals(SignStatus)) {
                                        dt.transState = "2";
                                    } else if ("1".equals(SignStatus)) {
                                        dt.transState = "3";
                                    } else if (com.fingard.text.StringHelper.hasAnyChar(values[4])) {
                                        dt.transState = "3";
                                    } else {
                                        dt.transState = "1";
                                    }
                                } else {
                                    dt.transState = "1";
                                }
                                dt.payInfo = values[4];
                                dt.authCode = values[0];
                                dt.iSeqno = values[0];
                                dt.oppAct = values[1];
                                dt.oppActName = values[2];
                                if (values.length > 5) {
                                    dt.contractNo = values[5];
                                }
                                retAts.writeRetDetail(dt);
                            }
                        }
                    }

                    reader.close();
                } catch (Exception ex) {
                    this.WriteBankLogLn(ex);
                } finally {
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (Exception ex) {
                            this.WriteBankLogLn(ex);
                        }
                    }
                }
                break;
            }
        }
        if (!isExistResult) {
            retAts.respInfo = "不存在结果文件";
            retAts.transState = "3";
            retAts.writeRetHead();
        }
        retAts.writeEnd();
        return retAts;
    }

    @Override
    public RetAtsQryRecAuthInfo d_qry_authInfo(ReqQryRecAuthInfo p_req) {
        return null;
    }
}
